package org.carl.base.feishu.bot.aspectj;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.carl.base.feishu.bot.annotation.FeiShuNotify;
import org.carl.base.feishu.bot.model.FeiShuBotRespResult;
import org.carl.base.feishu.bot.model.TextMsgModel;
import org.carl.base.feishu.bot.service.FeiShuBotService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 操作日志记录处理
 */
@Aspect
public class FeiShuNotifyAspect {
    private static final Logger LOG=Logger.getLogger(ClassUtil.getClassName(FeiShuNotifyAspect.class,true));
    @Autowired
    private FeiShuBotService feiShuBotService;
    /**
     * 表达式缓存
     */
    private static final Map<Integer,Expression> EXPRESSION_CAHCE=new ConcurrentHashMap<>();

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "@annotation(notify)")
    public void doAfterReturning(JoinPoint joinPoint, FeiShuNotify notify) {
        handleNotify(joinPoint, notify, null);
    }


    protected void handleNotify(final JoinPoint joinPoint, FeiShuNotify notify, final Exception e) {
        try {
            // 下面两个数组中，参数值和参数名的个数和位置是一一对应的。
            // 参数值
            Object[] args = joinPoint.getArgs();
            // 参数名
            String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();

            EvaluationContext context = new StandardEvaluationContext();
            for (int i = 0; i < args.length ; i++) {
                context.setVariable(argNames[i], args[i]);
                context.setVariable(("p"+i), args[i]);
            }
            boolean isContinue=true;
            if(StrUtil.isNotBlank(notify.condition())){
                Object condition = getExpression(notify.condition()).getValue(context);
                isContinue=Convert.toBool(condition,false);
            }
            if(!isContinue){
                //如果表达式为false,则不再执行
                LOG.log(Level.INFO,"发送飞书通知条件:"+notify.condition()+"不满足,不予执行.");
                return;
            }
            if(StrUtil.isBlank(notify.template())){
                return;
            }
            TextMsgModel textMsgModel=null;
            //如果参数列表为空则不需要解析参数
            if(notify.args()!=null&&notify.args().length>0){
                String[] notifyArgs = notify.args();
                String[] notifyParams = new String[notifyArgs.length];
                for (int i = 0; i < notifyArgs.length; i++) {
                    String param = getExpression(notifyArgs[i]).getValue(context, String.class);
                    notifyParams[i]=param;
                }
                textMsgModel=TextMsgModel.text(StrFormatter.format(notify.template(),notifyParams));
            }else {
                textMsgModel=TextMsgModel.text(StrFormatter.format(notify.template()));
            }
            FeiShuBotRespResult shuBotRespResult = feiShuBotService.sendBot(notify.botId(), textMsgModel);
            LOG.log(Level.INFO,"飞书通知发送结果:"+shuBotRespResult.toString());
        } catch (Exception exp) {
            LOG.log(Level.WARNING,"飞书通知发送失败:"+exp.getMessage(),exp);
        }
    }

    /**
     * 根据公式字符串获取编译公式
     * @param expression
     * @return
     */
    public static Expression getExpression(String expression){
        if(EXPRESSION_CAHCE.containsKey(expression.hashCode())){
            return EXPRESSION_CAHCE.get(expression.hashCode());
        }
        ExpressionParser parser = new SpelExpressionParser();
        Expression parseExpression=parser.parseExpression(expression);
        EXPRESSION_CAHCE.put(expression.hashCode(),parseExpression);
        return parseExpression;
    }
}
